/**
 * @file STL_Mysql.cpp
 * @author Derek Liu (yjkhtddx@sina.com)
 * @brief 
 * @version 0.1
 * @date 2020-09-30
 * 
 * @copyright Copyright Sci-Tech Laboratories (c) 2020
 * 
 */

#include "STL_Mysql.h"
#include <mysql/mysql.h>
#include <unistd.h>

namespace STL
{
    STL_Mysql::STL_Mysql(STL_Mysql::Option option) : m_option(option), m_status(STL_Mysql::Status::None)
    {
        printf("password:%s\n", m_option.password.c_str());
    }

    STL_Mysql::~STL_Mysql()
    {
        if (m_connection)
        {
            mysql_close(m_connection);
            m_connection = nullptr;
        }
    }

    void STL_Mysql::setStatus(STL_Mysql::Status status)
    {
        m_mutex.lock();
        m_status = status;
        m_mutex.unlock();
        if (m_statusCallback)
            m_statusCallback(m_status);
    }

    int STL_Mysql::start()
    {

        setStatus(STL_Mysql::Status::Init);

        /* Initialize the connection object */
        m_connection = mysql_init(NULL);
        if (m_connection == NULL)
        {
            fprintf(stderr, "Failed to initialize: %s\n", mysql_error(m_connection));
            setStatus(STL_Mysql::Status::Over);
            return -1;
        }

        /* Connect to the server */
        if (!mysql_real_connect(m_connection, m_option.host.c_str(), m_option.username.c_str(), m_option.password.c_str(), m_option.database.c_str(), m_option.prot, NULL, 0))
        {
            fprintf(stderr, "Failed to connect to server: %s\n", mysql_error(m_connection));
            setStatus(STL_Mysql::Status::Over);
            return -1;
        }

        printf("\nYou're now connected to the server.\n");
        setStatus(STL_Mysql::Status::Connected);

        m_run = true;
        setStatus(STL_Mysql::Status::Init);
        m_thread = std::thread(std::bind(&STL_Mysql::mysqlThread, this));
    }
    int STL_Mysql::stop()
    {
        m_run = false;
        //TODO 断开连接，停掉线程，注销对象
    }

    void STL_Mysql::mysqlThread()
    {
        MYSQL_RES *result;
        MYSQL_ROW row;
        unsigned int num_fields;
        std::string query;

        while (m_run)
        {

            if (m_QueryCallback)
            {
                query = m_QueryCallback();
                if (query.empty())
                {
                    usleep(10000);
                    continue;
                }
            }
            else
            {
                usleep(10000);
                continue;
            }

            // /* Execute the query */
            // if (mysql_query(m_connection, query.c_str()))
            // {
            //     fprintf(stderr, "Error querying server: %s\n", mysql_error(m_connection));
            //     continue;
            // }

            if (mysql_real_query(m_connection, query.data(), query.size()))
            {
                fprintf(stderr, "Error querying server: %s\n", mysql_error(m_connection));
                continue;
            }

            /* Get the result set */
            result = mysql_use_result(m_connection);
            if (result == NULL)
            {
                printf("No result.\n");
                continue;
            }

            /* Print all rows */
            num_fields = mysql_num_fields(result);
            while (row = mysql_fetch_row(result))
            {
                unsigned long *field_lengths = mysql_fetch_lengths(result);
                if (field_lengths == NULL)
                {
                    fprintf(stderr, "Failed to get field lengths: %s\n", mysql_error(m_connection));
                    continue;
                }
                for (int i = 0; i < num_fields; i++)
                {
                    printf("[%.*s] ", (int)field_lengths[i], row[i] ? row[i] : "NULL");
                }
                printf("\n");
            }
            /* Free result set */
            mysql_free_result(result);
            result = nullptr;
        }

        setStatus(STL_Mysql::Status::Over);
    }

} // namespace STL
